// Copyright (c) 2008 Matthew Johnson
// Licensed under the MIT License (see license.txt)
package actionml.interaction {
	import actionml.Global;

	import flash.display.DisplayObject;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.events.FocusEvent;
	import flash.events.MouseEvent;

	public class ButtonInteractions {
		public static function initialize() {
			Global.initializeExtension(ButtonInteractions, DisplayObject);
		}
		public static var instanceMethods:Object = {
			followLinkOnClick: function() {
				if (this.isAlready("FollowingLinkOnClick")) return;
				var o:Object = this;
				this.makeButton();
				this.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
					o.followLink();
				});
			},
			makeStateButton: function(options:Object = null) { 
				if (this.isAlready("StateButton")) return;
				this.makeButton(options);
				options ||= {};
				var transition:Boolean = options["transition"];
				var loop:Boolean = ("loop" in options && options["loop"] || !("loop" in options));
				var o:DisplayObject = this;
				this.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
					var state:String = o.currentLabel;
					o.showNextDisplayState(transition, loop);
					o.doEvent(state);
				});
			},
			makeTab: function(options:Object = null) {
				if (this.isAlready("Tab")) return;
				this.makeRadioButton(options);
				var o:DisplayObject = this;
				this.contentObjects ||= [];
				for each (var s:String in options["content"].split(/\s*,\s*/)) {
					this.contentObjects.push(this.getValueForKeypath(s));
				}
				this.addEventListener("selected", function() {
					for each (var tab:Object in o.radioGroup) {
						if (!tab) continue;
						if (tab != o) {
							for each (var hidden:Object in tab.contentObjects) {
								if (o.contentObjects.contains(hidden)) {
									continue;
								}
								if ("tweens" in hidden && "hide" in hidden.tweens) {
									hidden.playTween("hide");
								} else {
									hidden.hide();
								}
							}
						}
					}
					for each (var visible:Object in o.contentObjects) {
						if ("tweens" in visible && "show" in visible.tweens) {
							visible.playTween("show");
						} else {
							visible.show();
						}
					}
				});
			},
			makeRadioButton: function(options:Object = null) {
				if (this.isAlready("RadioButton")) return;
				this.makeButton(options);
				options ||= {};
				var groupName:String = options["groupName"] || "defaultRadioGroup";
				var transition:Boolean = options["transition"];
				this.root["radioGroups"] ||= {};
				this.root["radioGroups"][groupName] ||= [];
				this.root["radioGroups"][groupName].push(this);
				this.root["radioGroups"][groupName].selected ||= null;
				this.radioGroup = this.root["radioGroups"][groupName];
				var o:DisplayObject = this;
				this.select = function() {
					for (var i:int=0; i < this.root["radioGroups"][groupName].length; i++) {
						var button:DisplayObject = this.root["radioGroups"][groupName][i];
						if (button == o) {
							button.showChild("selected");
							if (button is MovieClip && "showDisplayState" in button && this.hasDisplayState("selected")) {
								button.showDisplayState("selected", transition);
							}
							if (this.root["radioGroups"][groupName].selected != button) {
								button.doEvent("selected");
							}
						} else {
							button.hideChild("selected");
							if (button is MovieClip && "showDisplayState" in button && this.hasDisplayState("normal")) {
								button.showDisplayState("normal", transition);
							}
							if (this.root["radioGroups"][groupName].selected == button) {
								button.doEvent("deselected");
							}
						}
					}
					this.root["radioGroups"][groupName].selected = o;
				}
				this.isSelected = function() {
					return this.root["radioGroups"][groupName].selected == this;
				}
				this.parent.getSelection ||= function(groupName:String="defaultRadioGroup") {
					return this.root["radioGroups"][groupName].selected;
				}				
				this.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
					o.select();
				});
				if (options["selected"]) {
					o.addEventListener("init", function() {
						o.removeEventListener("init", arguments.callee);
						o.select();	
					});
				}
			},
			makeLink: function(options:Object = null) {
				this.makeButton(options);
			},
			makeButton: function(options:Object = null) {
				if (this.isAlready("Button")) return;
				options ||= {};
				this.labelText = this.findChild("labelText", options);
				if (this.labelText) {
					this.getLabel = function() {
						return this.labelText.text;
					};
					this.setLabel = function(label:String) {
						this.labelText.text = label;
						if (this.focusIndicator && this.focusIndicator.labelText) {
							this.focusIndicator.labelText.text = label;
						}
					};
				}
				if ("label" in options) {	
					if (this.labelText) {
						this.setLabel(options["label"]);
					} else {
						// TODO: trace no label text error
					}
				}
				this.hit = this.findChild("hit", options) || this;
				var hit:DisplayObject = this.hit;
				hit.buttonMode = true;
				hit.useHandCursor = true;
				var o:DisplayObject = this;
				hit.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {
					o.doEvent("click", {dontDispatch: true});
					if (!o.handlingAccessibilityClick) {
						// flash has set the focus to the item clicked on
						// which can be confusing for mouse only users so
						// we null it out assuming most users are either
						// mouse users or keyboard users but not both
						// ideally we could set focus back to what it was
						// previously but this does not appear to be 
						// possible
						o.stage.focus = null;
					}
				});
				this.tabEnabled = true;
				if (options && options.focusIndicatorName is String) {
					this.displayIndicatorWhenFocused(options.focusIndicatorName);
				} else {
					this.displayIndicatorWhenFocused();
				}
				this.clickOnEnter();
			}
		};
	}
}